package com.baosight.risk.web.zbaa;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.core.MediaType;

import org.apache.commons.collections.CollectionUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.baosight.risk.api.rire.RiwaRiskWaringService;
import com.baosight.risk.api.xtaa.code.IXtaaCodeService;
import com.baosight.risk.api.xtaa.sequences.IXtaaSequencesService;
import com.baosight.risk.api.xtzy.IXtzyCompanyService;
import com.baosight.risk.api.xtzy.IXtzyIntegralService;
import com.baosight.risk.api.zbaa.IZbaaTargetService;
import com.baosight.risk.base.controller.BaseController;
import com.baosight.risk.common.annotation.Log;
import com.baosight.risk.common.bean.BeanUtils;
import com.baosight.risk.common.enums.BusinessType;
import com.baosight.risk.common.enums.Status;
import com.baosight.risk.common.result.AjaxResult;
import com.baosight.risk.common.utils.DateUtils;
import com.baosight.risk.common.utils.ExcelUtil;
import com.baosight.risk.common.utils.StringUtils;
import com.baosight.risk.service.xtaa.code.entity.XtaaCode;
import com.baosight.risk.service.xtzy.entity.XtzyCompany;
import com.baosight.risk.service.zbaa.entity.ZbaaTarget;
import com.baosight.risk.service.zbaa.entity.ZbaaTargetSend;
import com.baosight.risk.service.zbaa.vo.ZbaaTargetHomeIndexVO;
import com.baosight.risk.service.zbaa.vo.ZbaaTargetVO;
import com.baosight.risk.service.zbaa.vo.ZbaaTargetValueVO;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

@Slf4j
@RestController
@RequestMapping("/zbaa/target")
@Api(value = "风险指标", description = "风险指标", produces = MediaType.APPLICATION_JSON)
public class ZbaaTargetController extends BaseController {

    @Autowired
    private IXtzyIntegralService integralService;

    @Autowired
    private IZbaaTargetService targetService;

    @Autowired
    private IXtaaCodeService codeService;

    @Autowired
    private IXtaaSequencesService sequencesService;

    @Autowired
    private IXtaaCodeService xtaaCodeService;

    @Autowired
    private IXtzyCompanyService companyService;

    @Autowired
    private RiwaRiskWaringService waringService;

    /**
     * 修改根据ID查询
     *
     * @return
     */
    @GetMapping("/edit")
    @ApiOperation("根据ID查询")
    public AjaxResult edit(@RequestParam("id") String id) {
        ZbaaTargetVO target = targetService.getById(id);
        return success(target);
    }



    /**
     * 披露报告填报新增指标分页查询风险指标
     *
     * @param target
     * @return
     */
    @GetMapping("saveTargetList")
    @ApiOperation("披露报告填报新增指标分页查询风险指标")
    public AjaxResult saveTargetList(ZbaaTarget target, HttpServletRequest request) {
        String flag = request.getParameter("flag");
        String code = request.getParameter("code");
        if (StringUtils.isBlank(flag)) {
            log.info("风险指标查询参数：" + target.toString());
            startPage();
            List<ZbaaTarget> resultList = targetService.getRiskWarningStatusTargetList(target);
            return getResultPage(resultList);
        }
        return error("无数据");
    }

    /**
     * 分页查询风险指标
     *
     * @param target
     * @return
     */
    @GetMapping("list")
    @ApiOperation("分页查询风险指标")
    public AjaxResult select(ZbaaTarget target, HttpServletRequest request) {
        String flag = request.getParameter("flag");
        String code = request.getParameter("code");
        if (StringUtils.isBlank(flag)) {
            log.info("风险指标查询参数：" + target.toString());
            startPage();
            List<ZbaaTarget> resultList = targetService.getTargetList(target);
            return getResultPage(resultList);
        } else if (flag.equals("1")) {
            log.info("风险指标查询查询参数：" + target.toString());

            //仅查看外部数据
            List<XtaaCode> list = xtaaCodeService.selectAllSubsetByDDCode("ZBW");
            List<String> ddCodeList = new ArrayList<>();
            for (XtaaCode xtaaCode : list) {
                ddCodeList.add(xtaaCode.getDdCode());
            }

            startPage();
            List<ZbaaTarget> resultList = targetService.getTargetListByTagertTypes(target, ddCodeList, getUser());
            return getResultPage(resultList);
        }
        // 查询当前指标分类全部数据
        else if (flag.equals("2") && !StringUtils.isBlank(code)) {

            log.info("风险指标查询参数：" + code);

            // 获取当前选择指标的全部子数据Cod
            List<XtaaCode> list = codeService.selectAllSubsetByDDCode(code);
            List<String> ddCodeList = new ArrayList<>();
            for (XtaaCode xtaaCode : list) {
                ddCodeList.add(xtaaCode.getDdCode());
            }

            startPage();
            List<ZbaaTarget> resultList = targetService.getTargetListByTagertTypes(target, ddCodeList, getUser());
            return getResultPage(resultList);
        }
        // 查询当前指标分类，当前公司包含的数据
        else if (flag.equals("3")) {
            if (code == null) {
                code = "ZBN";
            }
            log.info("风险指标查询参数：" + code);

            // 获取当前选择指标的全部子数据Cod
            List<XtaaCode> list = codeService.selectAllSubsetByDDCode(code);
            List<String> ddCodeList = new ArrayList<>();
            for (XtaaCode xtaaCode : list) {
                ddCodeList.add(xtaaCode.getDdCode());
            }

            startPage();
            List<ZbaaTarget> resultList = targetService.getTargetListByTagertTypesAndUserComp(target, ddCodeList, getUser());

            // 对当前选择指标进行当前登录人公司过滤

            return getResultPage(resultList);
        }
        // 查询指标分类,从重点风险中获取指标
        else if (flag.equals("4")) {
            Calendar calendar = Calendar.getInstance();
            calendar.add(Calendar.YEAR, -1);
            String acctYear = DateUtils.format(calendar.getTime(), "YYYY");
            List<ZbaaTarget> resultList = waringService.getTargetByImport(acctYear, getUser().getExt1(), code);

            // 对当前选择指标进行当前登录人公司过滤
            return getResultPage(resultList);
        }
        return error("无数据");
    }

    /**
     * 根据用户查找已经订阅指标
     *
     * @return
     */
    @GetMapping("listByUser")
    @ApiOperation("根据用户查找订阅指标")
    public AjaxResult listByUser(HttpServletRequest request) {
        String targetName = request.getParameter("targetName");
        startPage();
        List<ZbaaTarget> result = targetService.getTargetListByUser(getUser(), targetName);
        return getResultPage(result);
    }

    /**
     * 保存风险指标
     *
     * @param target
     * @return
     */
    @PostMapping("save")
    //@RequiresPermissions("")
    @Log(title = "保存风险指标", businessType = BusinessType.INSERT)
    @ApiOperation("保存风险指标")
    public AjaxResult save(@RequestBody ZbaaTargetVO target) {
        log.info("保存指标参数：" + target.toString());
        Integer result = targetService.insertTarget(target);
        return toAjax(result);
    }

    /**
     * 订阅风险指标
     *
     * @return
     */
    @PostMapping("addOrder")
    @Log(title = "订阅风险指标")
    @ApiOperation("订阅风险指标")
    public AjaxResult addOrder(@RequestBody ZbaaTargetSend targetSend) {
        if (!integralService.checkOrderLimit()) {
            return error("当前用户等级已达订阅上限");
        }
        String result = targetService.addOrder(targetSend, getUser());
        return success(result);
    }

    /**
     * 取消订阅风险指标
     *
     * @param ids
     * @return
     */
    @PostMapping("deleteOrder")
    //@RequiresPermissions("")
    @ApiOperation("风险指标授权")
    public AjaxResult deleteOrder(@RequestBody List<String> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            log.error("参数不能为空 ！");
            return error("参数不能为空！");
        }

        Integer result = targetService.deleteOrder(ids);
        return toAjax(result);
    }

    /**
     * 修改风险指标
     *
     * @param target
     * @return
     */
    @PostMapping("update")
    //@RequiresPermissions("")
    @Log(title = "修改风险指标")
    @ApiOperation("修改风险指标")
    public AjaxResult update(@RequestBody ZbaaTargetVO target) {
        log.info("修改风险指标参数：" + target.toString());
        ZbaaTarget item = targetService.get(target.getId());
        if (null == item) {
            log.error("数据有误！");
            return error("数据有误！");
        }
        //初始化基本参数
        target = (ZbaaTargetVO) BeanUtils.updateBean(target);
        Integer result = targetService.updateTarget(target);
        return toAjax(result);
    }

    @PostMapping("enable")
    @Log(title = "启用风险指标", businessType = BusinessType.UPDATE)
    //@RequiresPermissions("")
    @ApiOperation("启用风险指标")
    public AjaxResult enableStatus(@RequestBody Map map) {
        List<String> idList = JSONArray.fromObject(map.get("ids"));
        List<ZbaaTarget> targetList = targetService.getTargetByIds(idList);
        if (idList.size() != targetList.size()) {
            log.error("数据有误！");
            return error("数据有误！");
        }
        return toAjax(targetService.updateStatus(idList, Status.EFFECTIVE.getValue(), Status.EFFECTIVE.getDescription()));
    }

    @PostMapping("disable")
    @Log(title = "禁用风险指标", businessType = BusinessType.UPDATE)
    //@RequiresPermissions("")
    @ApiOperation("禁用风险指标")
    public AjaxResult disableStatus(@RequestBody Map map) {
        List<String> idList = JSONArray.fromObject(map.get("ids"));
        List<ZbaaTarget> targetList = targetService.getTargetByIds(idList);
        if (idList.size() != targetList.size()) {
            log.error("数据有误！");
            return error("数据有误！");
        }
        return toAjax(targetService.updateStatus(idList, Status.DISABLE.getValue(), Status.DISABLE.getDescription()));
    }

    @PostMapping("updateStatus")
    @Log(title = "状态修改", businessType = BusinessType.DELETE)
    @RequiresPermissions("")
    @ApiOperation("状态修改")
    public AjaxResult updateStatus(String ids, String status, String statusName) {
        List<String> idss = JSONArray.fromObject(ids);
        List<ZbaaTarget> targetList = targetService.getTargetByIds(idss);
        if (idss.size() != targetList.size()) {
            log.error("数据有误！");
            return error("数据有误！");
        }
        return toAjax(targetService.updateStatus(idss, status, statusName));
    }

    @PostMapping("externalInterface")
    @ApiOperation("外部接口")
    public AjaxResult externalInterface() throws Exception {
        return toAjax(targetService.externalInterface());
    }

    @PostMapping("getHistory")
    @ApiOperation("获取指标数据的历史值数据")
    public AjaxResult getHistory(@RequestParam("targetIds") List<String> targetIds, @RequestParam("count") Integer count) {
        return getResultPage(targetService.getHistory(targetIds, count));
    }

    /**
     * @return result
     * @description 描述
     * @author CuiShiHao
     * targetNo 指标编号
     * compCode 公司编号
     * startTime 开始时间
     * endTime 结束时间
     * flag 查询权限面板标识 1代表所属部门数据 0代表全部数据
     */
    @PostMapping("getValue")
    @ApiOperation("根据指标，公司,日期范围，查询权限获取指标值")
    public AjaxResult getValue(@RequestBody Map map) {
        String targetNo = map.get("targetNo").toString();
        String compCode = "";
        if (!"ZBW0000".equals(targetNo)){
            compCode = map.get("compCode").toString();
        }

        String startTime = paserDateStr(map.get("startTime").toString());
        String endTime = paserDateStr(map.get("endTime").toString());
        String period = map.get("period").toString();
        String flag = map.get("flag").toString();

        if ("1".equals(flag)) {
            List<String> titleList = DateUtils.getRangeList(startTime, endTime, period);
            List<ZbaaTargetValueVO> resultList = new ArrayList<>();

            //部门为空时查询当前用户所属全部部门数据
            if (StringUtils.isEmpty(compCode)) {

                // 根据订阅信息获取订阅组织
                List<XtzyCompany> companylist = targetService.getXtzyCompanyByTargetNo(targetNo);
                List<String> companyCodeList = new ArrayList<>();
                for (int i = 0; i < companylist.size(); i++) {
                    companyCodeList.add(companylist.get(i).getCompCode());
                }
                if (companyCodeList.size() != 0) {
                    resultList = targetService.getValue(targetNo, companyCodeList, startTime, endTime, period);
                }
            }
            //仅查询当前compCode数据
            else {
                List<String> companyCodeList = new ArrayList<>();
                companyCodeList.add(compCode);
                resultList = targetService.getValue(targetNo, companyCodeList, startTime, endTime, period);
            }

            // resultList 更新订阅信息
            List<ZbaaTarget> orderList = targetService.getTargetListByUser(getUser(), null);
            List<ZbaaTarget> filterList = orderList.stream().filter(o -> o.getTargetNo().equals(targetNo)).collect(Collectors.toList());
            for (ZbaaTargetValueVO zbaaTargetValueVO : resultList) {
                zbaaTargetValueVO.setOrderStatus("0");
                for (ZbaaTarget orderInfo : filterList) {
                    if (orderInfo.getCompCode().equals(zbaaTargetValueVO.getCompCode())) {
                        zbaaTargetValueVO.setOrderStatus("1");
                        zbaaTargetValueVO.setOrderID(orderInfo.getId());
                    }
                }
            }
            //拼接返还结果
            Map<String, Object> result = new HashMap();
            result.put("titleList", titleList);
            result.put("resultList", resultList);
            return success(result);
        }
        return success("成功", "");
    }

    private String paserDateStr(String dateStr){
    	String dateStrArr[] = dateStr.split("-");
    	String mothStr = dateStrArr[1];
    	String dayStr = dateStrArr[2];
    	return dateStrArr[0]+"-"+StringUtils.leftPad(mothStr, 2, "0")+"-"+StringUtils.leftPad(dayStr, 2, "0");
    }

    /**
     * 根据用户查找已经订阅的各个指标数据
     *
     * @return
     */
    @GetMapping("orderDataByUser")
    @ApiOperation("根据用户查找订阅指标")
    public AjaxResult orderDataByUser(HttpServletRequest request) {
        List<List<ZbaaTargetValueVO>> resultList = new ArrayList<>();

        // 获取当前用户全部订阅指标
        List<ZbaaTarget> orderList = targetService.getTargetListByUser(getUser(), "");
        for (ZbaaTarget zbaaTarget : orderList) {
            String targetNo = zbaaTarget.getTargetNo();
            String compCode = zbaaTarget.getCompCode();
            String period = zbaaTarget.getExt5();
            String endTime = DateUtils.format(new Date(), "yyyy-MM-dd");
            String interval = "10";
            String startTime = DateUtils.caculateTime(endTime, period, interval);
            if (period.equals("季")) {
                endTime = "";
                interval = "4";
            }
            List<String> companyCodeList = new ArrayList<>();
            companyCodeList.add(compCode);
            List<ZbaaTargetValueVO> result = targetService.getValue(targetNo, companyCodeList, startTime, endTime, period);
            resultList.add(result);
        }
        return success(resultList);
    }

    /**
     * @return result
     * @description 获取首页行业需求指标（对比信息）
     * @author CuiShiHao
     */
    @GetMapping("getHomeIndex")
    @ApiOperation("获取首页行业需求指标")
    public AjaxResult getHomeIndex() {
        List<ZbaaTargetHomeIndexVO> result = targetService.getHomeIndex();
        return success("成功", result);
    }

    /**
     * @return result
     * @description 获取首页行业需求指标(图标信息)
     * @author CuiShiHao
     */
    @GetMapping("getHomeIndexDataList")
    @ApiOperation("获取首页行业需求指标图表")
    public AjaxResult getHomeIndexDataList() {
        List<List<ZbaaTargetValueVO>> result = targetService.getHomeIndexDataList();
        return success("成功", result);
    }

    /**
     * 获取首页行业需求指标状态
     *
     * @return
     */
    @GetMapping("getHomeIndexStatus")
    @ResponseBody
    @ApiOperation("获取首页行业需求指标状态")
    public AjaxResult getHomeIndexStatus() {
        Object result = targetService.getHomeIndexStatus();
        if (result == null) {
            return error();
        }
        return success("成功", result);
    }

    /**
     * @return result
     * @description 获取指标相关性分析结果
     * @author CuiShiHao
     */
    @PostMapping("getAnaylseResult")
    @ApiOperation("获取指标相关性分析结果")
    public AjaxResult getAnaylseResult(@RequestBody Map map) {
        JSONObject result = targetService.getAnaylzeResult(map);
        return success("成功", result);
    }

    /**
     * 获取上季度指标值
     *
     * @return
     */
    @GetMapping("queryTargetValue")
    @ResponseBody
    @ApiOperation("获取上季度指标值")
    public AjaxResult queryTargetValue(String targetNo, String compCode) {
        if ("null".equals(compCode)) compCode = null;
        return success("查询成功", targetService.getTargetValue(targetNo, compCode));
    }

    /**
     * 获取指标参考值
     *
     * @return
     */
    @GetMapping("queryReferenceValue")
    @ResponseBody
    @ApiOperation("获取指标参考值")
    public AjaxResult queryReferenceValue(String targetNo, String compCode, String acctYear, String quarterCode) {
        if ("null".equals(compCode)) compCode = null;
        if (StringUtils.isBlank(acctYear) || StringUtils.isBlank(quarterCode)) {
            return error("缺少年度季度信息，无法获取参考值");
        }
        return success("查询成功", targetService.getReferenceValue(targetNo, compCode, acctYear, quarterCode));
    }

    /**
     * 更新/新增指标参考值
     *
     * @return
     */
    @GetMapping("updateReferenceValue")
    @ResponseBody
    @ApiOperation("更新/新增指标参考值")
    public AjaxResult updateReferenceValue(String targetNo, String targetName, String compCode, String acctYear, String quarterCode, String targetValue) {
        if ("null".equals(compCode)) compCode = null;
        if (StringUtils.isBlank(acctYear) || StringUtils.isBlank(quarterCode)) {
            return error("缺少年度季度信息，无法获取参考值");
        }
        return success("更新成功", targetService.updateReferenceValue(targetNo, targetName, compCode, acctYear, quarterCode, targetValue));
    }


    /**
     * 传入开始时间、结束时间计算指标值
     *
     * @return
     */
    @PostMapping("updateTargetActualValues")
    @ResponseBody
    @ApiOperation("手动更新披露报告指标实际值到指标值库中")
    public AjaxResult updateTargetActualValues() {
        targetService.getUpdateActualValueTarget();
        return success("更新成功");
    }

    /**
     * 导出excel全部
     *
     * @return
     */
    @PostMapping("exportALL")
    @ResponseBody
    @ApiOperation("导出全部风险指标")
    public AjaxResult exportAllExcel(@RequestBody ZbaaTarget target) {
        log.info("导出风险指标：" + target.toString());
        ExcelUtil<ZbaaTarget> excel = new ExcelUtil<>(ZbaaTarget.class);

        List<ZbaaTarget> resultList = targetService.getTargetList(target);
        List<String> columNameList = new ArrayList<>(Arrays.asList("targetNo", "targetName", "targetDesc", "targetType", "targetPeriod","targetFormula","manageCompName"));
        return excel.exportExcel(resultList, "全部风险指标", columNameList);
    }

    /**getValue
     * 导出excel外部
     *
     * @return
     */
    @PostMapping("exportOut")
    @ResponseBody
    @ApiOperation("导出外部风险指标")
    public AjaxResult exportZBWExcel(@RequestBody ZbaaTarget target) {
        //仅查看外部数据
        List<XtaaCode> list = xtaaCodeService.selectAllSubsetByDDCode("ZBW");
        List<String> ddCodeList = new ArrayList<>();
        for (XtaaCode code : list) {
            ddCodeList.add(code.getDdCode());
        }

        List<ZbaaTarget> resultList = targetService.getTargetListByTagertTypes(target, ddCodeList, getUser());

        log.info("导出外部风险指标：" + target.toString());
        ExcelUtil<ZbaaTarget> excel = new ExcelUtil<>(ZbaaTarget.class);

        return excel.exportExcel(resultList, "外部风险指标", null);
    }

    /**
     * 传入开始时间、结束时间计算指标值
     *
     * @return
     */
    @PostMapping("calculateTarget")
    @ResponseBody
    @ApiOperation("定时任务计算指标值")
    public void calculateTarget(String startDate, String endDate) throws Exception {
        targetService.calculateTarget(startDate, endDate);
    }

    /**
     * 构建个人指标分析的树
     *
     */
    @GetMapping(value = "/targetTree")
    @ApiOperation("构建个人指标分析的树")
    public AjaxResult targetTree(String queryFlag){
        return AjaxResult.success("查询成功", targetService.getTargetTree(queryFlag));
    }

}
